package com.sheng.leetcode.year2023.month07.day11;

import org.junit.Test;

import java.util.Arrays;

/**
 * @author liusheng
 * @date 2023/07/11
 * <p>
 * 188. 买卖股票的最佳时机 IV<p>
 * <p>
 * 给定一个整数数组 prices ，它的第 i 个元素 prices[i] 是一支给定的股票在第 i 天的价格，和一个整型 k 。<p>
 * 设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。也就是说，你最多可以买 k 次，卖 k 次。<p>
 * 注意：你不能同时参与多笔交易（你必须在再次购买前出售掉之前的股票）。<p>
 * <p>
 * 示例 1：<p>
 * 输入：k = 2, prices = [2,4,1]<p>
 * 输出：2<p>
 * 解释：在第 1 天 (股票价格 = 2) 的时候买入，<p>
 * 在第 2 天 (股票价格 = 4) 的时候卖出，这笔交易所能获得利润 = 4-2 = 2 。<p>
 * <p>
 * 示例 2：<p>
 * 输入：k = 2, prices = [3,2,6,5,0,3]<p>
 * 输出：7<p>
 * 解释：在第 2 天 (股票价格 = 2) 的时候买入，在第 3 天 (股票价格 = 6) 的时候卖出, 这笔交易所能获得利润 = 6-2 = 4 。<p>
 * 随后，在第 5 天 (股票价格 = 0) 的时候买入，在第 6 天 (股票价格 = 3) 的时候卖出, 这笔交易所能获得利润 = 3-0 = 3 。<p>
 * <p>
 * 提示：<p>
 * 0 <= k <= 100<p>
 * 0 <= prices.length <= 1000<p>
 * 0 <= prices[i] <= 1000<p>
 * <p>
 * 来源：力扣（LeetCode）<p>
 * 链接：<a href="https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-iv">188. 买卖股票的最佳时机 IV</a><p>
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。<p>
 */
public class LeetCode0188 {

    @Test
    public void test01() {
        int k = 2;
//        int[] prices = {2, 4, 1};
        int[] prices = {3, 2, 6, 5, 0, 3};
        System.out.println(new Solution188().maxProfit(k, prices));
    }
}

class Solution188 {
    public int maxProfit(int k, int[] prices) {
        // buy[i] 表示买入 i 次股票后的利润
        int[] buy = new int[k + 1];
        // sell[i] 表示完成 i 笔交易后的利润
        int[] sell = new int[k + 1];
        Arrays.fill(buy, -prices[0]);
        for (int i = 1; i < prices.length; i++) {
            // 最多支持 k 次交易
            for (int j = 1; j <= k; j++) {
                // 买入 j 次后的最大利润为：Math.max(当前利润, 上一笔交易的利润-当天的股票价格)
                buy[j] = Math.max(buy[j], sell[j - 1] - prices[i]);
                // 完成 j 次交易后的最大利润为：Math.max(当前利润, 当前利润+本次交易后所得的利润)
                sell[j] = Math.max(sell[j], buy[j] + prices[i]);
            }
        }
        return sell[k];
    }
}
